package com.tkmybatis.hfy.base.service.impl;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import com.tkmybatis.common.GlobalConstant;
import com.tkmybatis.hfy.base.entity.*;
import com.tkmybatis.hfy.base.mapper.BaseMapper;
import com.tkmybatis.hfy.base.service.BaseService;
import com.tkmybatis.hfy.utils.SnowFlakeUtil;
import com.tkmybatis.hfy.utils.StringUtils;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.CacheManager;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import tk.mybatis.mapper.entity.Example;
import tk.mybatis.mapper.entity.Example.Criteria;
import tk.mybatis.mapper.mapperhelper.EntityHelper;


@Slf4j
public abstract class BaseServiceImpl<T extends BaseEntity> implements BaseService<T> {
    
    private final static int PAGE_NUMBER = 1;
    private final static int PAGE_SIZE = 10;
	
	public abstract BaseMapper<T> getMapper();
	
	@Autowired
    private CacheManager cacheManager;
	
	@Override
	public T selectOne(T record) {
		record.setDelFlg(GlobalConstant.DELETE_N);
		List<T> results = getMapper().select(record);
		if(CollectionUtils.isNotEmpty(results)) return results.get(0);
		else return null;
	}
	/**
	 * 根据实体类不为null的字段进行查询,条件全部使用=号and条件
	 * @param record 影响行数
	 * @return list 列表
	 */
	@Override
	public List<T> select(T record) {
		record.setDelFlg(GlobalConstant.DELETE_N);
		return getMapper().select(record);
	}
	
	@Override
	public List<T> queryList(Map<String, Object> paramMap){
		paramMap.put("del_flg", GlobalConstant.DELETE_N);
	    return getMapper().queryList(paramMap);
	}
	
	@Override
	public List<T> queryListByLike(Map<String, Object> paramMap){
		paramMap.put("del_flg", GlobalConstant.DELETE_N);
	    return getMapper().queryListByLike(paramMap);
	}
	
	
	@Override
	public Long queryCount(Map<String, Object> paramMap){
		paramMap.put("del_flg", GlobalConstant.DELETE_N);
	    return getMapper().queryCount(paramMap);
	}
	
	@Override
	public List<Map<String,Object>> queryListMap(Map<String, Object> paramMap) throws Exception{
		paramMap.put("del_flg", GlobalConstant.DELETE_N);
		return getMapper().queryListMap(paramMap);
	}
	
	@Override
	public List<Map<String,Object>> queryListMapByLike(Map<String, Object> paramMap) throws Exception{
		paramMap.put("del_flg", GlobalConstant.DELETE_N);
		return getMapper().queryListMapByLike(paramMap);
	}
	
	@Override
    public PageBean<Map<String, Object>> queryListMapPageByLike(Map<String, Object> paramMap) throws Exception{
		setPage(paramMap);
		paramMap.put("del_flg", GlobalConstant.DELETE_N);
        List<Map<String, Object>> list = getMapper().queryListMapByLike(paramMap);
        //用PageInfo对结果进行包装
        PageBean<Map<String, Object>> pageInfo = new PageBean<Map<String, Object>>(list);
        return pageInfo;
    }
	
	/**
	 * 设置分页
	 * @param paramMap
	 */
	public void setPage(Map<String, Object> paramMap) {
		if(paramMap.get("pageNumber") == null || StringUtils.isBlank(paramMap.get("pageNumber").toString())){
            paramMap.put("pageNumber", PAGE_NUMBER);
        }
        if(paramMap.get("pageSize") == null || StringUtils.isBlank(paramMap.get("pageSize").toString())){
            paramMap.put("pageSize", PAGE_SIZE);
        }
        if (paramMap.get("sortName")!=null) {
            PageHelper.startPage(Integer.parseInt(paramMap.get("pageNumber").toString()), Integer.parseInt(paramMap.get("pageSize").toString()), HumpConvert.humpToLine2(paramMap.get("sortName").toString()) +" "+ paramMap.get("sortOrder"));
        }else{
            PageHelper.startPage(Integer.parseInt(paramMap.get("pageNumber").toString()), Integer.parseInt(paramMap.get("pageSize").toString()));
        }
	}

	public void setPage(Pageable page) {
		if(page.getPageNumber()==0){
			page.setPageNumber(PAGE_NUMBER);
		}
		if(page.getPageSize()==0){
			page.setPageSize(PAGE_SIZE);
		}
		if (StringUtils.isNotBlank(page.getSortName())) {
			PageHelper.startPage(page.getPageNumber(),page.getPageSize(), HumpConvert.humpToLine2(page.getSortName() +" "+ page.getSortOrder()));
		}else{
			PageHelper.startPage(page.getPageNumber(),page.getPageSize());
		}
	}


	public void setPage(Integer pageNumber, Integer pageSize) {
        PageHelper.startPage(pageNumber, pageSize);

	}
	
	public <T> BootStrapPage<T> getBootStrapPage(PageInfo<T> pageInfo) throws Exception {
        BootStrapPage<T> page = new BootStrapPage<T>();
        page.setTotal(pageInfo.getTotal());
        page.setRows(pageInfo.getList());
        return page;
    }
	
	@Override
    public PageBean<T> queryListPageByLike(Map<String, Object> paramMap) throws Exception{
		setPage(paramMap);
		paramMap.put("del_flg", GlobalConstant.DELETE_N);
        List<T> list = getMapper().queryListByLike(paramMap);
        //用PageInfo对结果进行包装
        PageBean<T> pageInfo = new PageBean<T>(list);
        return pageInfo;
    }
	
	/**
	 * 根据实体类不为null的字段进行查询，条件全部使用=号and条件，并指定排序
	 * @param record 查询条件
	 * @param orderSqlStr 排序条件 （name ase,id desc）
	 * @return List 列表
	 */
	public List<T> select(T record,String orderSqlStr){
		Example example = new Example(record.getClass(),false);
		Criteria criteria = example.createCriteria();
		Map<String, String> map;
		try {
			record.setDelFlg(GlobalConstant.DELETE_N);
			map = BeanUtils.describe(record);
			for(Entry<String, String> entry : map.entrySet()){
				if(entry.getValue() == null || "".equals(entry.getValue())) continue;
					criteria.andEqualTo(entry.getKey(), entry.getValue());
			}
			example.setOrderByClause(orderSqlStr);
			return getMapper().selectByExample(example);
		} catch (Exception e) {
			throw new RuntimeException(e.getMessage(),e);
		}
	}
	
	/**
	 * 根据实体类不为null的字段查询总数,条件全部使用=号and条件
	 * @param record 对象
	 * @return int  影响行数
	 */
	@Override
	public int selectCount(T record) {
		record.setDelFlg(GlobalConstant.DELETE_N);
		return getMapper().selectCount(record);
	}

	/**
	 * 根据主键进行查询,必须保证结果唯一 单个字段做主键时,可以直接写主键的值 联合主键时,key可以是实体类,也可以是Map
	 * 
	 * @param key 主键
	 * @return T  影响行数
	 */
	@Override
	public T selectByPrimaryKey(Object key) {
		return getMapper().selectByPrimaryKey(key);
	}

	/**
	 * 插入一条数据 支持Oracle序列,UUID,类似Mysql的INDENTITY自动增长(自动回写)
	 * 优先使用传入的参数值,参数值空时,才会使用序列、UUID,自动增长
	 * 
	 * @param record 对象
	 * @return int 影响行数
	 */
	@Override
	public int insert(T record) {
		if(StringUtils.isBlank(record.getId())) {
			String id = SnowFlakeUtil.nextId();
	        record.setId(id+"");
		}
	    setCreateDefault(record);
		return getMapper().insertSelective(record);
	}
	
	public int insertBatch(List<T> record) {
	    int num = 0;
	    for(T t : record) {
	        num ++;
	        if(StringUtils.isBlank(t.getId())) {
				String id = SnowFlakeUtil.nextId();
		        t.setId(id+"");
			}
	        setCreateDefault(t);
	        getMapper().insert(t);
	    }
	    return num;
	}
	
	/**
     * 新增时，获取当前操作人，操作时间
     * @author ywt
     * @date 2018年5月3日 下午4:05:11
     * @version 1.0
     * @param record
     * @return
     */
	public T setCreateDefault(T record) {
		Date now = new Date();
        record.setInsTime(now);
        record.setUpdTime(now);
        record.setDelFlg(GlobalConstant.DELETE_N);
	    try {
	       // CurrentUser currentUser = UserUtils.getCurrentUser();
//	        if(currentUser != null) {
//	        	record.setInsUserId(currentUser.getId());
//	        	record.setUpdUserId(currentUser.getId());
//	        }
        } catch (Exception e) {
            log.error("error:",e);
        }
	    return record;
	}

	/**
	 * 更新时，获取当前操作人，操作时间
	 * @author ywt
	 * @date 2018年5月3日 下午4:05:11
	 * @version 1.0
	 * @param record
	 * @return
	 */
	public T setUpdateDefault(T record) {
		Date now = new Date();
        record.setUpdTime(now);
	    try {
//	        CurrentUser currentUser = UserUtils.getCurrentUser();
//	        if(currentUser != null) {
//	        	record.setUpdUserId(currentUser.getId());
//	        }
        } catch (Exception e) {
            log.error("error:",e);
        }
        return record;
    }

	/**
	 * 插入一条数据,只插入不为null的字段,不会影响有默认值的字段
	 * 支持Oracle序列,UUID,类似Mysql的INDENTITY自动增长(自动回写)
	 * 优先使用传入的参数值,参数值空时,才会使用序列、UUID,自动增长
	 * 
	 * @param record 对象
	 * @return int 影响行数
	 */
	@Override
	public int insertSelective(T record) {
		if(StringUtils.isBlank(record.getId())) {
			String id = SnowFlakeUtil.nextId();
			record.setId(id+"");
		}
        setCreateDefault(record);
		return getMapper().insertSelective(record);
	}

	/**
	 * 根据实体类不为null的字段进行查询,条件全部使用=号and条件
	 * 
	 * @param key 主键
	 * @return int 影响行数
	 */
	@Override
	public int delete(T key) {
		int i=0; 
		List<T> list = this.select(key);
		for(T t : list) {
			t.setDelFlg(GlobalConstant.DELETE_Y);
			this.save(t);
			i++;
		}
		return i;
	}
	
	@Override
	public int deleteTrue(T key) {
		return getMapper().delete(key);
	}
	
	@Override
	public void deleteByParam(Map<String, Object> paramMap) {
		List<T> list = this.queryList(paramMap);
		for(T t : list) {
			t.setDelFlg(GlobalConstant.DELETE_Y);
			this.save(t);
		}
	}
	
	@Override
	public void deleteByParamTrue(Map<String, Object> paramMap) {
		getMapper().deleteByParam(paramMap);
	}
	
	@Override
	public int deleteBatch(List<String> list) {
	    int num = 0;
	    for(String t : list) {
	        num ++;
	        this.deleteByPrimaryKey(t);
	    }
	    return num;
	}
	
	@Override
	public int deleteBatchTrue(List<String> list) {
	    int num = 0;
	    for(String t : list) {
	        num ++;
	        this.deleteByPrimaryKeyTrue(t);
	    }
	    return num;
	}

	/**
	 * 通过主键进行删除,这里最多只会删除一条数据 单个字段做主键时,可以直接写主键的值 联合主键时,key可以是实体类,也可以是Map
	 * 
	 * @param key 主键
	 * @return int 影响行数
	 */
	@Override
	public int deleteByPrimaryKey(Object key) {
		T record = this.selectByPrimaryKey(key);
		record.setDelFlg(GlobalConstant.DELETE_Y);
		return this.updateByPrimaryKeySelective(record);
	}
	
	@Override
	public int deleteByPrimaryKeyTrue(Object key) {
		return getMapper().deleteByPrimaryKey(key);
	}

	/**
	 * 根据主键进行更新,这里最多只会更新一条数据 参数为实体类
	 * 
	 * @param record 对象
	 * @return int 影响行数
	 */
	@Override
	public int updateByPrimaryKey(T record) {
	  setUpdateDefault(record);
		return getMapper().updateByPrimaryKey(record);
	}

	/**
	 * 根据主键进行更新 只会更新不是null的数据
	 * 
	 * @param record 对象
	 * @return int 影响行数
	 */
	@Override
	public int updateByPrimaryKeySelective(T record) {
	    setUpdateDefault(record);
		return getMapper().updateByPrimaryKeySelective(record);
	}

	/**
	 * 保存或者更新，根据传入id主键是不是null来确认
	 * 
	 * @param record 对象
	 * @return int 影响行数
	 */
	@Override
	public int save(T record) {
		int count = 0;
		if (StringUtils.isEmpty(record.getId())) {
			count = this.insertSelective(record);
		} else {
			count = this.updateByPrimaryKeySelective(record);
		}
		return count;
	}

	/**
   	 *(单表分页可排序) 
   	 * @param pageNum 当前页
   	 * @param pageSize 页码
   	 * @param record 对象
   	 * @return PageBean 分页对象
   	 */
	@Override
	public PageBean<T> selectPage(int pageNum, int pageSize, T record) {
		PageHelper.startPage(pageNum, pageSize);
		record.setDelFlg(GlobalConstant.DELETE_N);
		return new PageBean<T>(getMapper().select(record));
	}
	
	@Override
    public PageBean<T> selectPageLike(int pageNum, int pageSize, T record) {
	    Example example = new Example(record.getClass(),false);
        Criteria criteria = example.createCriteria();
        Map<String, Object> map;
        try {
        	record.setDelFlg(GlobalConstant.DELETE_N);
            map = PropertyUtils.describe(record);
            for(Entry<String, Object> entry : map.entrySet()){
                if(entry.getValue() == null || "".equals(entry.getValue())) continue;
                criteria.andLike(entry.getKey(), "%"+entry.getValue().toString()+"%");
            }
            PageHelper.startPage(pageNum, pageSize);
            List<T> list = getMapper().selectByExample(example);
            return new PageBean<T>(list);
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }
	
	/**
	 * (单表分页可排序) 
	 * @param pageNum 当前页
	 * @param pageSize 页码
	 * @param record 对象
	 * @param orderSqlStr (如:id desc)
	 * @return PageBean 分页对象
	 */
	@Override
	public PageBean<T> selectPage(int pageNum, int pageSize, T record,String orderSqlStr) {
		Example example = new Example(record.getClass(),false);
		Criteria criteria = example.createCriteria();
		Map<String, Object> map;
		try {
			record.setDelFlg(GlobalConstant.DELETE_N);
			map = PropertyUtils.describe(record);
			for(Entry<String, Object> entry : map.entrySet()){
				if(entry.getValue() == null || "".equals(entry.getValue())) continue;
				criteria.andEqualTo(entry.getKey(), entry.getValue());
			}
			example.setOrderByClause(orderSqlStr);
			PageHelper.startPage(pageNum, pageSize);
			List<T> list = getMapper().selectByExample(example);
			return new PageBean<T>(list);
		} catch (Exception e) {
			throw new RuntimeException(e.getMessage(), e);
		}
	}

	@Override
    public PageBean<T> selectPageLike(int pageNum, int pageSize, T record,String orderSqlStr) {
        Example example = new Example(record.getClass(),false);
        Criteria criteria = example.createCriteria();
        Map<String, Object> map;
        try {
        	record.setDelFlg(GlobalConstant.DELETE_N);
            map = PropertyUtils.describe(record);
            for(Entry<String, Object> entry : map.entrySet()){
                if(entry.getValue() == null || "".equals(entry.getValue())) continue;
                criteria.andLike(entry.getKey(), "%"+entry.getValue().toString()+"%");
            }
            example.setOrderByClause(orderSqlStr);
            PageHelper.startPage(pageNum, pageSize);
            List<T> list = getMapper().selectByExample(example);
            return new PageBean<T>(list);
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }
	
	@Override 
	public List<T> betweenSelect(T record, BetweenSelect betweenSelect){
		Example example = new Example(record.getClass(),false);
		Criteria criteria = example.createCriteria();
		Map<String, String> map;
		try {
			record.setDelFlg(GlobalConstant.DELETE_N);
			map = BeanUtils.describe(record);
			for(Entry<String, String> entry : map.entrySet()){
				if(entry.getValue() == null || "".equals(entry.getValue())) continue;
					criteria.andEqualTo(entry.getKey(), entry.getValue());
			}
			if(betweenSelect != null) {
				Object value1 = betweenSelect.getValue1();
				if(value1 != null && StringUtils.isBlank(value1.toString())) {
					value1 = null;
				}
				Object value2 = betweenSelect.getValue2();
				if(value2 != null && StringUtils.isBlank(value2.toString())) {
					value2 = null;
				}
				criteria.andBetween(betweenSelect.getProperty(), value1, value2);
			}
			String orderBy = EntityHelper.getOrderByClause(record.getClass());
			if(StringUtils.isNotBlank(orderBy)) {
				example.setOrderByClause(orderBy);
			}
			return getMapper().selectByExample(example);
		} catch (Exception e) {
			throw new RuntimeException(e.getMessage(),e);
		}
	}
	public List<T> findProjectByIdList(Map<String, Object> paramMap) {
		paramMap.put("del_flg", GlobalConstant.DELETE_N);
	    return getMapper().findProjectByIdList(paramMap);
	}
	
}
